#pragma once
#include"entityfactory.h"

#if 0
#define _DECLARE_ENTITY_ \
	virtual entityfactory_t* getfactory() const;\
	static entityfactory_t* getclassfactory();\
	static int getclasstypeid(){return getclassfactory()->type;}

#define _DEFINE_ENTITY_(_class_,_parent_) \
struct _class_##factory_t:entityfactory_t \
{\
	\
};
#endif


enum
{
	ENTITY_ACTIVE =(1<<0),
	ENTITY_VALID_WORLDMTX = (1<<1),
	ENTITY_TO_BE_ACTIVATED = (1<<2),
	ENTITY_DYNAMIC_ERASE_IF_POSSIBLE = (1<<3),
	ENTITY_DYNAMIC = (1<<4),

	ENTITY_LASTFLAG = (1<<31)
};

struct json_object_t;

struct entity_t
{
	DECLARE_ENTITY;

	int get_typeid() const{return get_metaobject()->get_typeid();}
	bool isa(int type_id) const {return get_metaobject()->isa(type_id);}


	static entityfactory_t* factory;

	entity_t();
	virtual ~entity_t();

	virtual void onload();
	virtual void init();
	virtual void update();
	virtual void exit();
	virtual void render();
	virtual void messagehandler(const stringhash& messageID, const json_object_t& messageparam);

	virtual void initrecursive();
	virtual void updaterecursive();
	virtual void exitrecursive();
	virtual void renderrecursive(bool everything=false);

#ifdef LEO_DESIGNER
	virtual void onchangeproperty(const stringhash& propname);
	void save_recursive(string& s);
	void save_to_file(const char* filename);
#endif
	void init_script_function_ids();

	bool isactive() const;
	void activate();
	void deactivate();

	void initthis();

	entity_t* getnextpo(entity_t* root) const;
	entity_t* getnextpo_up(entity_t* root) const;

	bool isflagset(int flag) const;
	void setflag(int flag);
	void clearflag(int flag);

	void addchild(entity_t* e);
	void add_after(entity_t* e);
	void add_before(entity_t* e);

	void removechild(entity_t* e);

	void eraserecursive();

	entity_t* clonerecursive();
	entity_t* clone();

	void setlocalmtx(const float4x4& m);
	void setworldmtx(const float4x4& m);
	void setworldposition(const float3& v);
	const float4x4& getworldmtx();
	void validateworldmtx();
	void invalidateworldmtx();

	virtual void prepare_to_die(){}
	void prepare_to_die_recursive()
	{
		for (entity_t* ptr=this; ptr; ptr=ptr->getnextpo(this))
			ptr->prepare_to_die();
	}
	virtual bool is_erasable(){return true;}

#ifdef LEO_DESIGNER
	float4x4 getinitialworldmtx();
	void setinitialworldmtx(const float4x4&);
	bool selected;
#endif




	entity_t* prev;
	entity_t* next;
	entity_t* child;
	entity_t* lastchild;
	entity_t* parent;

	uint32 flags;
	float4x4 localmtx;
	float4x4 worldmtx;

	int script_init_func_id;
	int script_update_func_id;
	int script_exit_func_id;
	int script_msg_func_id;
	int script_type_id;
	void* script_object;

	int entityID;


	uint32 gethashkey() const
	{
		return name.value;
	}

	entity_t* nextinhashmap;


//properties
	bool activate_at_startup;
	float4x4 initiallocalmtx;
	stringhash name;

	string script_type;
//	string script_init_function_name;
//	string script_update_function_name;
//	string script_exit_function_name;
//	string script_message_handler_function_name;
	json_object_t script_parameters;
	json_object_t script_states;



};

struct entity_ptr_t
{
	int entityID;
	entity_t* get();

	entity_ptr_t()
	{
		entityID=0;
	}

	entity_ptr_t(entity_t* e)
	{
		entityID=e->entityID;
	}
};

namespace entity_id_server
{
	void add_entity(entity_t* e);
	void add_entity_with_current_id(entity_t* e);
	void remove_entity(entity_t* e);
	void init();
	entity_t* get_entity(int id);
};

entity_t* load_scene_from_file(const char* filename);